#include <errno.h>
#include <stdlib.h>
// K: I couldn't compile this without including sys/types.h for off_t definition.
//#include <sys/types.h>
#include "struct_essentials.h"
#define FOREST 57
/*My realisation of list*/
size_t MEM, MEM_USED;
off_t TOTAL, TOTAL_USED, SWAP, SWAP_USED;
struct RBtree* tree[FOREST];
list *delim;
/*It is init function nothing to do here)*/

void* DataInit(size_t mem, off_t swap, size_t total)
{
	MEM = mem;
	SWAP = swap;
	TOTAL = swap;
	
	MEM_USED = 0;
	SWAP_USED = 0;
	TOTAL_USED = 0;
	int i,j;
	for(i=0;i<FOREST;i++){
		if(create(&tree[i])==NULL){
			goto fail;
		}
	}
	delim = (list*) malloc(sizeof(list));
	if(delim == NULL){
		
	}
	delim->mnext=delim->mprev=delim->snext=delim->sprev=delim->tnext=delim->tprev=delim;
	return tree;
fail:
	for(j=i-1;j>=0;j--){
		destroy(&tree[j]);
	}
	errno = ENOMEM;
	return NULL;
}

/*Find list record by id*/

list* findListById(size_t id)
{
	if (delim == (list*) 0) {
		return 0;
	}
	// K: this if is unnecessary, considering that next for is already checking the same condition.
	if(delim->tnext==delim){
		goto fail;
	}
	list* i;
	i=(list*)search(tree[id%FOREST], id);
	return i;
fail:
	errno = EFAULT;
	return(list*) 0;
	
}


/*Add data record to list*/

list* addData(size_t id, size_t size)
{
	if (delim == (list*) 0) {
		return (list*) 0;
	}
	list* new_rec = (list*) malloc(sizeof(list));
	if(new_rec == NULL){
		goto fail;
	}
	new_rec->tnext=delim;
	new_rec->tprev=delim->tprev;
	delim->tprev = new_rec;
	new_rec->tprev->tnext=new_rec;
	new_rec->id = id;
	new_rec->refcnt = 0;
	new_rec->offset = -1;
	new_rec->ptr = NULL;
	new_rec->size = size;
	new_rec->mnext=NULL;
	new_rec->mprev=NULL;
	new_rec->sprev=NULL;
	new_rec->snext=NULL;
	new_rec->node=insert(tree[id%FOREST],id,new_rec);
	if(new_rec->node == NULL){
		goto fail;
	}
	return new_rec;
fail:	
	errno = ENOMEM;
	return NULL;
}
/*Remove data record from list*/


void removeFromSRing(list* removeMe){
	if (removeMe->sprev) {
		removeMe->snext->sprev = removeMe->sprev;
		removeMe->sprev->snext = removeMe->snext;
		removeMe->snext=NULL;
		removeMe->sprev=NULL;
		SWAP_USED -=removeMe->size;
	}
}
void removeFromMRing(list* removeMe){
	if (removeMe->mprev) {
		removeMe->mnext->mprev = removeMe->mprev;
		removeMe->mprev->mnext = removeMe->mnext;
		removeMe->mnext=NULL;
		removeMe->mprev=NULL;
		MEM_USED -= removeMe->size;;
	}
}
void removeFromTRing(list* removeMe){
	removeMe->tnext->tprev = removeMe->tprev;
	removeMe->tprev->tnext = removeMe->tnext;
	removeFromMRing(removeMe);
	removeFromSRing(removeMe);
	TOTAL_USED -=removeMe->size;
	removeBP(tree[removeMe->id%FOREST],removeMe->node);
	free(removeMe);
	
}
/*Free all */

void DataDeinit()
{
	if (delim == (list*) 0) {
		return;
	}
	list *i=delim->tnext;
	while(i!=delim){
		i=i->tnext;
		free(i->tprev);
	}
	free(delim);
	int j;
	for(j=0;j<FOREST;j++)
		destroy(&tree[j]);
	return;
}


